package com.tools.web.work.captcha;

import com.tools.common.exception.IORuntimeException;
import com.tools.common.io.FileKit;
import com.tools.common.object.Note;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;

/**
 * 滑动验证图片的构建实例
 * */
@Note("滑动验证图片的构建实例")
public class SlideCaptchaBuilder {

    @Note("滑动的背景源图")
    private BufferedImage srcImage;

    @Note("背景图的自定义宽度")
    private int imageWidth = -1;

    @Note("背景图的自定义高度")
    private int imageHeight = -1;

    @Note("滑动块的宽度")
    private int blockWidth;

    @Note("滑动块的高度")
    private int blockHeight;

    @Note("滑动块的半径")
    private int blockRadius;

    @Note("源画布背景的后缀名，默认为 PNG")
    private String srcImageSuffix = "PNG";

    @Note("阻塞块的后缀名，默认为 PNG")
    private String blockSuffix = "PNG";

    @Note("允许的误差像素值")
    private int faultTolerant;

    @Note("允许错误的次数。大于 0 才生效")
    private int allowErrorCount;

    /* ********************************************************************************************
     *
     *          构造器
     *
     * *********************************************************************************************
     * */

    public SlideCaptchaBuilder(BufferedImage srcImage) {
        this.setSrcImage(srcImage);
    }

    public SlideCaptchaBuilder(InputStream srcImageStream) {
        this.setSrcImage(srcImageStream);
    }

    public SlideCaptchaBuilder(File srcImageFile) {
        this.setSrcImage(srcImageFile);
    }

    public SlideCaptchaBuilder(String srcImageFilePath) {
        this.setSrcImage(srcImageFilePath);
    }

    public static SlideCaptchaBuilder build(BufferedImage srcImage) {
        return new SlideCaptchaBuilder(srcImage);
    }

    public static SlideCaptchaBuilder build(InputStream srcImageStream) {
        return new SlideCaptchaBuilder(srcImageStream);
    }

    public static SlideCaptchaBuilder build(File srcImageFile) {
        return new SlideCaptchaBuilder(srcImageFile);
    }

    public static SlideCaptchaBuilder build(String srcImageFilePath) {
        return new SlideCaptchaBuilder(srcImageFilePath);
    }

    /* ********************************************************************************************
     *
     *          Getter / Setter
     *
     * *********************************************************************************************
     * */

    public BufferedImage getSrcImage() {
        return srcImage;
    }

    public void setSrcImage(BufferedImage srcImage) {
        if(srcImage == null) throw new NullPointerException("源背景图为 null");
        this.srcImage = srcImage;
    }

    public void setSrcImage(InputStream srcImageStream) {
        if(srcImageStream == null) throw new NullPointerException("源背景图的字节输入流为 null");
        try {
            this.srcImage = ImageIO.read(srcImageStream);
        } catch (IOException e) {
            throw new IORuntimeException(e);
        }
    }


    public void setSrcImage(File srcImageFile) {
        if(srcImageFile == null) throw new NullPointerException("源背景图的文件实例为 null");
        try {
            this.srcImage = ImageIO.read(srcImageFile);
        } catch (IOException e) {
            throw new IORuntimeException(e);
        }
    }

    public void setSrcImage(String srcImageFilePath) {
        if(srcImageFilePath == null) throw new NullPointerException("源背景图的文件实例为 null");
        try {
            this.srcImage = ImageIO.read(new File(srcImageFilePath));
        } catch (IOException e) {
            throw new IORuntimeException(e);
        }
    }

    public int getImageWidth() {
        return (imageWidth < 0) ? srcImage.getWidth() : imageWidth;
    }

    public void setImageWidth(int imageWidth) {
        this.imageWidth = imageWidth;
    }


    public int getImageHeight() {
        return (imageHeight < 0) ? srcImage.getHeight() : imageHeight;
    }

    public void setImageHeight(int imageHeight) {
        this.imageHeight = imageHeight;
    }

    public int getBlockWidth() {
        return (blockWidth <= 0) ? (int) (imageWidth / 4.9) : blockWidth;
    }

    public void setBlockWidth(int blockWidth) {
        this.blockWidth = blockWidth;
    }

    public int getBlockHeight() {
        return (blockHeight <= 0) ? (int) (imageHeight / 2.8) : blockHeight;
    }

    public void setBlockHeight(int blockHeight) {
        this.blockHeight = blockHeight;
    }

    public int getBlockRadius() {
        return (blockRadius <= 0) ? (int) (blockWidth / 7.2) : blockRadius;
    }

    public void setBlockRadius(int blockRadius) {
        this.blockRadius = blockRadius;
    }

    public String getSrcImageSuffix() {
        return srcImageSuffix;
    }

    public void setSrcImageSuffix(String srcImageSuffix) {
        if(FileKit.isFileSuffix(srcImageSuffix)) this.srcImageSuffix = srcImageSuffix;
    }

    public String getBlockSuffix() {
        return blockSuffix;
    }

    public void setBlockSuffix(String blockSuffix) {
        if(FileKit.isFileSuffix(blockSuffix)) this.blockSuffix = blockSuffix;
    }

    public int getFaultTolerant() {
        return faultTolerant;
    }

    public void setFaultTolerant(int faultTolerant) {
        this.faultTolerant = Math.abs(faultTolerant);
    }

    public int getAllowErrorCount() {
        return allowErrorCount;
    }

    public void setAllowErrorCount(int allowErrorCount) {
        this.allowErrorCount = allowErrorCount;
    }

    @Override
    public String toString() {
        return "SlideCaptchaBuilder{" +
                "srcImage=" + srcImage +
                ", imageWidth=" + imageWidth +
                ", imageHeight=" + imageHeight +
                ", blockWidth=" + blockWidth +
                ", blockHeight=" + blockHeight +
                ", blockRadius=" + blockRadius +
                ", srcImageSuffix=" + srcImageSuffix +
                ", blockSuffix=" + blockSuffix +
                ", faultTolerant=" + faultTolerant +
                ", allowErrorCount=" + allowErrorCount +
                '}';
    }

    /* ********************************************************************************************
     *
     *          链式调用
     *
     * *********************************************************************************************
     * */

    public SlideCaptchaBuilder srcImage(BufferedImage srcImage) {
        this.setSrcImage(srcImage);
        return this;
    }

    public SlideCaptchaBuilder srcImage(InputStream srcImageStream) {
        this.setSrcImage(srcImageStream);
        return this;
    }

    public SlideCaptchaBuilder srcImage(File srcImageFile) {
        this.setSrcImage(srcImageFile);
        return this;
    }


    public SlideCaptchaBuilder srcImage(String srcImageFilePath) {
        this.setSrcImage(srcImageFilePath);
        return this;
    }

    public SlideCaptchaBuilder imageWidth(int imageWidth) {
        this.setImageWidth(imageWidth);
        return this;
    }

    public SlideCaptchaBuilder imageHeight(int imageHeight) {
        this.setImageHeight(imageHeight);
        return this;
    }

    public SlideCaptchaBuilder blockWidth(int blockWidth) {
        this.setBlockWidth(blockWidth);
        return this;
    }

    public SlideCaptchaBuilder blockHeight(int blockHeight) {
        this.setBlockHeight(blockHeight);
        return this;
    }

    public SlideCaptchaBuilder blockRadius(int blockRadius) {
        this.setBlockRadius(blockRadius);
        return this;
    }

    public SlideCaptchaBuilder srcImageSuffix(String srcImageSuffix) {
        this.setSrcImageSuffix(srcImageSuffix);
        return this;
    }

    public SlideCaptchaBuilder blockSuffix(String blockSuffix) {
        this.setBlockSuffix(blockSuffix);
        return this;
    }

    public SlideCaptchaBuilder blockSuffix(int faultTolerant) {
        this.setFaultTolerant(faultTolerant);
        return this;
    }

    public SlideCaptchaBuilder allowErrorCount(int allowErrorCount) {
        this.setAllowErrorCount(allowErrorCount);
        return this;
    }
}
